#ifndef MOCHA_DETAIL_EVENT_QUEUE_HPP_INCLUDED
#define MOCHA_DETAIL_EVENT_QUEUE_HPP_INCLUDED

/**
 * @file
 */

#include <string>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include "mocha/events.hpp"
#include "mocha/event_queue_plugin.hpp"
#include "mocha/object_importer.hpp"
#include "mocha/plugin_proxy.hpp"
#include "mocha/pointers.hpp"

namespace mocha {
/**
 * Event queue.
 * Exposes system events when pumped, which typically occurs at the end of each cycle.
 * Used heavily by core components and forms the backbone of the messaging system.
 * Not truly a queue, because events may be accessed in arbitrary order (and in groups). However, insertion is always queue-like.
 * @see event
 */
class event_queue : public plugin_proxy<event_queue_plugin>, public boost::noncopyable {
public:
	typedef std::vector<event> buffer_type;
	typedef std::vector<const event* const> const_buffer_type;
	typedef boost::function<bool (const event&)> predicate_type;
	event_queue(plugin_factory_ptr_t factory, const std::string& name, const object_importer& importer);
	~event_queue();
	/**
	 * Pumps the queue, pushing new events.
	 * No events are removed.
	 */
	void pump();
	/**
	 * Removes all events.
	 * The events are lost after the operation.
	 * @see dump
	 */
	void clear();
	/**
	 * Removes all events.
	 * Returns a buffer of the events, but can be slow.
	 * @return Event buffer containing the events previously in the queue.
	 * @see clear
	 */
	buffer_type dump();
	/**
	 * Pushes an event onto the back of the queue.
	 */
	void push(const event& e);
	/**
	 * Pushes the events in a buffer onto the back of the queue.
	 * @param events Buffer of events.
	 */
	void push(const buffer_type& events);
	/**
	 * Pops (removes) the next event off the front of the queue.
	 * @param e Next event at the front of the queue. Unmodified if no such event exists.
	 * @return Non-zero if there was an event to pop, otherwise zero.
	 */
	int pop(event& e);
	/**
	 * Pops (removes) the next event matching a type mask, starting from the queue's front.
	 * @param e Next event matching a type mask. Unmodified if no such event exists.
	 * @param type Event type mask.
	 * @return Non-zero if a matching event was found, otherwise zero.
	 * @see pop_all
	 * @see event_type_mask
	 */
	int pop(event& e, int type);
	/**
	 * Pops (removes) all events matching a type mask.
	 * @param type Event type mask.
	 * @return Buffer of all events matching a type mask. Can be empty.
	 * @see event_type_mask
	 */
	buffer_type pop_all(int type);
	/**
	 * Pops (removes) all events satisfying a predicate.
	 * @param f Predicate function (functor).
	 * @return Buffer of all events satisfying a predicate. Can be empty.
	 */
	buffer_type pop_if(predicate_type f);
};
/**
 * Convenience function to detect quit events in an event queue.
 * @param queue Event queue.
 * @return Number of quit events found in the queue (zero if there is no quit event).
 */
size_t has_quit(const_event_queue_ptr_t queue);
}

#endif

